﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using GeneralDFS.BusinessLogical;
using GeneralDFS.BusinessLogical.Config;
using GeneralDFS.BusinessLogical.Nodes;
using GeneralDFS.DataEntity.Config;
using GeneralDFS.DataEntity.Enum;
using GeneralDFS.DataEntity.Nodes;
using GeneralDFS.Interface.Nodes;
using GeneralDFS.BusinessLogical.Chord;
using NIF.MobileActors.Hosts;

namespace General_Disturbed_File_System
{
    public class Program
    {
        private static ConfigCenter _configCenter;
        private static List<Thread> _threads;
        private static List<IBaseNode> _baseNodes;

        public static void Main(string[] args)
        {
            //设置CurrentDomain的assembly resolver 
            AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs e) =>
                {
                    var asmName = new AssemblyName(e.Name);
                    byte[] bytes = AssemblyManager.Instance.GetRawAssembly(asmName.FullName);
                    if (bytes == null)
                    {
                        return null;
                    }
                    var xAsm = Assembly.Load(bytes);  //装载程序集
                    return xAsm;
                };

            Init();
            InitNodes();
            Console.WriteLine(StartNodes());
            Console.ReadKey();
            int[,] hopCountMap;
            List<NameNodeInfo> nodeList;
            MapImage.GenerateMap(_configCenter.GetConfig().NameNodeInfos()[0], out nodeList, out hopCountMap);
            MapImage.GenerateImage(hopCountMap, nodeList,"output.jpg");
            StopNodes();
        }

        public static void Init()
        {
            LogUtil.Setup();//初始化日志组件
            _configCenter=new ConfigCenter(); //初始化配置中心
            _threads=new List<Thread>();
            _baseNodes=new List<IBaseNode>();
        }

        private static void InitNodes()
        {
            var nodeType = _configCenter.GetConfig().DetailConfig.Mode.ToLower();
            switch (nodeType)
            {
                case "local":
                   LogUtil.LogInfo("You are using local mode to debug this application");
                    foreach (var nameNodeConfig in _configCenter.GetConfig().NameNodeConfigs)
                    {
                        var nameNode = CreateNode.Create(_configCenter.GetConfig(),nameNodeConfig, NodeType.NameNode);
                        nameNode.ConfigLocal(new CurrentSettings { Index = _configCenter.GetConfig().NameNodeConfigs.IndexOf(nameNodeConfig), NodeType = NodeType.NameNode });
                        var nameNodeThread = new Thread(nameNode.Start);
                        _threads.Add(nameNodeThread);
                        _baseNodes.Add(nameNode);
                    }
                    foreach (var dataNodeConfig in _configCenter.GetConfig().DataNodeConfigs)
                    {
                        var dataNode = CreateNode.Create(_configCenter.GetConfig(), dataNodeConfig, NodeType.DataNode);
                        dataNode.ConfigLocal(new CurrentSettings { Index = _configCenter.GetConfig().DataNodeConfigs.IndexOf(dataNodeConfig), NodeType = NodeType.DataNode });
                        var dataNodeThread = new Thread(dataNode.Start);
                        _threads.Add(dataNodeThread);
                        _baseNodes.Add(dataNode);
                    }
                    break;
                case "network":
                    if (_configCenter.GetConfig().CurrentSettings.NodeType == NodeType.NameNode)
                    {
                        var nameNodeConfig = _configCenter.GetConfig().NameNodeConfigs[_configCenter.GetConfig().CurrentSettings.Index];
                        var nameNode = CreateNode.Create(_configCenter.GetConfig(), nameNodeConfig, NodeType.NameNode);
                        var nameNodeThread = new Thread(nameNode.Start);
                        _threads.Add(nameNodeThread);
                        _baseNodes.Add(nameNode);
                    }
                    else if (_configCenter.GetConfig().CurrentSettings.NodeType == NodeType.DataNode)
                    {
                        var dataNodeConfig = _configCenter.GetConfig().DataNodeConfigs[_configCenter.GetConfig().CurrentSettings.Index];
                        var dataNode = CreateNode.Create(_configCenter.GetConfig(), dataNodeConfig, NodeType.DataNode);
                        var dataNodeThread = new Thread(dataNode.Start);
                        _threads.Add(dataNodeThread);
                        _baseNodes.Add(dataNode);
                    }
                    break;
            }
        }

        /// <summary>
        /// 启动所有节点
        /// </summary>
        /// <returns>成功启动的节点数</returns>
        private static int StartNodes()
        {
            var recv = 0;
            foreach (var thread in _threads)
            {
                thread.Start();
                Console.ReadKey();
                //Thread.Sleep(1000);
                recv++;
            }
            return recv;
        }

        /// <summary>
        /// 停止所有节点
        /// </summary>
        /// <returns></returns>
        public static int StopNodes()
        {
            var recv = 0;
            foreach (var thread in _threads)
            {
                _baseNodes[recv].Stop();
                if(thread.ThreadState==ThreadState.Running)
                    thread.Abort();
                recv++;
            }
            return recv;
        }
    }
}